home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Half-Life Model Viewer / src / GlWindow.cpp < prev    next >
C/C++ Source or Header  |  1999-10-20  |  14KB  |  634 lines

  1. //
  2. //                 Half-Life Model Viewer (c) 1999 by Mete Ciragan
  3. //
  4. // file:           GlWindow.cpp
  5. // last modified:  May 04 1999, Mete Ciragan
  6. // copyright:      The programs and associated files contained in this
  7. //                 distribution were developed by Mete Ciragan. The programs
  8. //                 are not in the public domain, but they are freely
  9. //                 distributable without licensing fees. These programs are
  10. //                 provided without guarantee or warrantee expressed or
  11. //                 implied.
  12. //
  13. // version:        1.2
  14. //
  15. // email:          mete@swissquake.ch
  16. // web:            http://www.swissquake.ch/chumbalum-soft/
  17. //
  18. #include <mx/mx.h>
  19. #include <mx/mxMessageBox.h>
  20. #include <mx/mxTga.h>
  21. #include <mx/mxPcx.h>
  22. #include <mx/mxBmp.h>
  23. #include <mx/gl.h>
  24. #include <GL/glu.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <time.h>
  28. #include <string.h>
  29. #include "GlWindow.h"
  30. #include "StudioModel.h"
  31. #include "ViewerSettings.h"
  32.  
  33.  
  34.  
  35. extern char g_appTitle[];
  36. extern bool g_bStopPlaying;
  37.  
  38.  
  39.  
  40. GlWindow *g_GlWindow = 0;
  41. vec3_t g_vright = { 50, 50, 0 };        // needs to be set to viewer's right in order for chrome to work
  42. float g_lambert = 1.5;
  43.  
  44.  
  45.  
  46. GlWindow::GlWindow (mxWindow *parent, int x, int y, int w, int h, const char *label, int style)
  47. : mxGlWindow (parent, x, y, w, h, label, style)
  48. {
  49.     glDepthFunc (GL_LEQUAL);
  50.  
  51.     if (!parent)
  52.         setVisible (true);
  53.     else
  54.         mx::setIdleWindow (this);
  55. }
  56.  
  57.  
  58.  
  59. GlWindow::~GlWindow ()
  60. {
  61.     mx::setIdleWindow (0);
  62.     loadTexture (0, 0);
  63.     loadTexture (0, 1);
  64. }
  65.  
  66.  
  67.  
  68. int
  69. GlWindow::handleEvent (mxEvent *event)
  70. {
  71.     static float oldrx = 0, oldry = 0, oldtz = 50, oldtx = 0, oldty = 0;
  72.     static int oldx, oldy;
  73.  
  74.     switch (event->event)
  75.     {
  76.  
  77.     case mxEvent::Idle:
  78.     {
  79.         g_studioModel.SetBlending (0, 0.0);
  80.         g_studioModel.SetBlending (1, 0.0);
  81.  
  82.         static float prev;
  83.         float curr = (float) mx::getTickCount () / 1000.0f;
  84.  
  85.         if (!g_bStopPlaying)
  86.             g_studioModel.AdvanceFrame ((curr - prev) * g_viewerSettings.speedScale);
  87.  
  88.         prev = curr;
  89.  
  90.         if (!g_viewerSettings.pause)
  91.             redraw ();
  92.  
  93.         return 1;
  94.     }
  95.     break;
  96.  
  97.     case mxEvent::MouseDown:
  98.     {
  99.         oldrx = g_viewerSettings.rot[0];
  100.         oldry = g_viewerSettings.rot[1];
  101.         oldtx = g_viewerSettings.trans[0];
  102.         oldty = g_viewerSettings.trans[1];
  103.         oldtz = g_viewerSettings.trans[2];
  104.         oldx = event->x;
  105.         oldy = event->y;
  106.         g_viewerSettings.pause = false;
  107.  
  108.         return 1;
  109.     }
  110.     break;
  111.  
  112.     case mxEvent::MouseDrag:
  113.     {
  114.         if (event->buttons & mxEvent::MouseLeftButton)
  115.         {
  116.             if (event->modifiers & mxEvent::KeyShift)
  117.             {
  118.                 g_viewerSettings.trans[0] = oldtx - (float) (event->x - oldx);
  119.                 g_viewerSettings.trans[1] = oldty + (float) (event->y - oldy);
  120.             }
  121.             else
  122.             {
  123.                 g_viewerSettings.rot[0] = oldrx + (float) (event->y - oldy);
  124.                 g_viewerSettings.rot[1] = oldry + (float) (event->x - oldx);
  125.             }
  126.         }
  127.         else if (event->buttons & mxEvent::MouseRightButton)
  128.         {
  129.             g_viewerSettings.trans[2] = oldtz + (float) (event->y - oldy);
  130.         }
  131.         redraw ();
  132.  
  133.         return 1;
  134.     }
  135.     break;
  136.  
  137.     case mxEvent::KeyDown:
  138.     {
  139.         switch (event->key)
  140.         {
  141.         case 32:
  142.         {
  143.             int iSeq = g_studioModel.GetSequence ();
  144.             if (iSeq == g_studioModel.SetSequence (iSeq + 1))
  145.             {
  146.                 g_studioModel.SetSequence (0);
  147.             }
  148.         }
  149.         break;
  150.  
  151.         case 27:
  152.             if (!getParent ()) // fullscreen mode ?
  153.                 mx::quit ();
  154.             break;
  155.  
  156.         case 'g':
  157.             g_viewerSettings.showGround = !g_viewerSettings.showGround;
  158.             if (!g_viewerSettings.showGround)
  159.                 g_viewerSettings.mirror = false;
  160.             break;
  161.  
  162.         case 'h':
  163.             g_viewerSettings.showHitBoxes = !g_viewerSettings.showHitBoxes;
  164.             break;
  165.  
  166.         case 'o':
  167.             g_viewerSettings.showBones = !g_viewerSettings.showBones;
  168.             break;
  169.  
  170.         case '5':
  171.             g_viewerSettings.transparency -= 0.05f;
  172.             if (g_viewerSettings.transparency < 0.0f)
  173.                 g_viewerSettings.transparency = 0.0f;
  174.  
  175.             break;
  176.  
  177.         case '6':
  178.             g_viewerSettings.transparency += 0.05f;
  179.             if (g_viewerSettings.transparency > 1.0f)
  180.                 g_viewerSettings.transparency = 1.0f;
  181.  
  182.             break;
  183.  
  184.         case 'b':
  185.             g_viewerSettings.showBackground = !g_viewerSettings.showBackground;
  186.             break;
  187.  
  188.         case 's':
  189.             g_viewerSettings.useStencil = !g_viewerSettings.useStencil;
  190.             break;
  191.  
  192.         case 'm':
  193.             g_viewerSettings.mirror = !g_viewerSettings.mirror;
  194.             if (g_viewerSettings.mirror)
  195.                 g_viewerSettings.showGround = true;
  196.             break;
  197.  
  198.         case '1':
  199.         case '2':
  200.         case '3':
  201.         case '4':
  202.             g_viewerSettings.renderMode = event->key - '1';
  203.             break;
  204.  
  205.         case '-':
  206.             g_viewerSettings.speedScale -= 0.1f;
  207.             if (g_viewerSettings.speedScale < 0.0f)
  208.                 g_viewerSettings.speedScale = 0.0f;
  209.             break;
  210.  
  211.         case '+':
  212.             g_viewerSettings.speedScale += 0.1f;
  213.             if (g_viewerSettings.speedScale > 5.0f)
  214.                 g_viewerSettings.speedScale = 5.0f;
  215.             break;
  216.         }
  217.     }
  218.     break;
  219.  
  220.     } // switch (event->event)
  221.  
  222.     return 1;
  223. }
  224.  
  225.  
  226.  
  227. void
  228. drawFloor ()
  229. {
  230.     if (g_viewerSettings.use3dfx)
  231.     {
  232.         glBegin (GL_TRIANGLE_STRIP);
  233.         glTexCoord2f (1.0f, 0.0f);
  234.         glVertex3f (100.0f, 100.0f, 0.0f);
  235.  
  236.         glTexCoord2f (1.0f, 1.0f);
  237.         glVertex3f (100.0f, -100.0f, 0.0f);
  238.  
  239.         glTexCoord2f (0.0f, 0.0f);
  240.         glVertex3f (-100.0f, 100.0f, 0.0f);
  241.  
  242.         glTexCoord2f (0.0f, 1.0f);
  243.         glVertex3f (-100.0f, -100.0f, 0.0f);
  244.  
  245.         glEnd ();
  246.     }
  247.     else
  248.     {
  249.         glBegin (GL_TRIANGLE_STRIP);
  250.         glTexCoord2f (0.0f, 0.0f);
  251.         glVertex3f (-100.0f, 100.0f, 0.0f);
  252.  
  253.         glTexCoord2f (0.0f, 1.0f);
  254.         glVertex3f (-100.0f, -100.0f, 0.0f);
  255.  
  256.         glTexCoord2f (1.0f, 0.0f);
  257.         glVertex3f (100.0f, 100.0f, 0.0f);
  258.  
  259.         glTexCoord2f (1.0f, 1.0f);
  260.         glVertex3f (100.0f, -100.0f, 0.0f);
  261.  
  262.         glEnd ();
  263.     }
  264. }
  265.  
  266.  
  267.  
  268. void
  269. setupRenderMode ()
  270. {
  271.     if (g_viewerSettings.renderMode == RM_WIREFRAME)
  272.     {
  273.         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
  274.         glDisable (GL_TEXTURE_2D);
  275.         glDisable (GL_CULL_FACE);
  276.         glEnable (GL_DEPTH_TEST);
  277.     }
  278.     else if (g_viewerSettings.renderMode == RM_FLATSHADED ||
  279.             g_viewerSettings.renderMode == RM_SMOOTHSHADED)
  280.     {
  281.         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  282.         glDisable (GL_TEXTURE_2D);
  283.         glEnable (GL_CULL_FACE);
  284.         glEnable (GL_DEPTH_TEST);
  285.  
  286.         if (g_viewerSettings.renderMode == RM_FLATSHADED)
  287.             glShadeModel (GL_FLAT);
  288.         else
  289.             glShadeModel (GL_SMOOTH);
  290.     }
  291.     else if (g_viewerSettings.renderMode == RM_TEXTURED)
  292.     {
  293.         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  294.         glEnable (GL_TEXTURE_2D);
  295.         glEnable (GL_CULL_FACE);
  296.         glEnable (GL_DEPTH_TEST);
  297.         glShadeModel (GL_SMOOTH);
  298.     }
  299. }
  300.  
  301.  
  302.  
  303. void
  304. GlWindow::draw ()
  305. {
  306.     glClearColor (g_viewerSettings.bgColor[0], g_viewerSettings.bgColor[1], g_viewerSettings.bgColor[2], 0.0f);
  307.  
  308.     if (g_viewerSettings.useStencil)
  309.         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  310.     else
  311.         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  312.  
  313.     glViewport (0, 0, w2 (), h2 ());
  314.  
  315.     //
  316.     // show textures
  317.     //
  318.  
  319.     if (g_viewerSettings.showTexture)
  320.     {
  321.         glMatrixMode (GL_PROJECTION);
  322.         glLoadIdentity ();
  323.  
  324.         glOrtho (0.0f, (float) w2 (), (float) h2 (), 0.0f, 1.0f, -1.0f);
  325.  
  326.         studiohdr_t *hdr = g_studioModel.getTextureHeader ();
  327.         if (hdr)
  328.         {
  329.             mstudiotexture_t *ptextures = (mstudiotexture_t *) ((byte *) hdr + hdr->textureindex);
  330.             float w = (float) ptextures[g_viewerSettings.texture].width * g_viewerSettings.textureScale;
  331.             float h = (float) ptextures[g_viewerSettings.texture].height * g_viewerSettings.textureScale;
  332.  
  333.             glMatrixMode (GL_MODELVIEW);
  334.             glPushMatrix ();
  335.             glLoadIdentity ();
  336.  
  337.             glDisable (GL_CULL_FACE);
  338.  
  339.             glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  340.             float x = ((float) w2 () - w) / 2;
  341.             float y = ((float) h2 () - h) / 2;
  342.  
  343.             glDisable (GL_TEXTURE_2D);
  344.             glColor4f (1.0f, 0.0f, 0.0f, 1.0f);
  345.             glRectf (x - 2, y - 2, x  + w + 2, y + h + 2);
  346.  
  347.             glEnable (GL_TEXTURE_2D);
  348.             glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
  349.             glBindTexture (GL_TEXTURE_2D, g_viewerSettings.texture + 3); //d_textureNames[0]);
  350.  
  351.             glBegin (GL_TRIANGLE_STRIP);
  352.  
  353.             glTexCoord2f (0, 0);
  354.             glVertex2f (x, y);
  355.  
  356.             glTexCoord2f (1, 0);
  357.             glVertex2f (x + w, y);
  358.  
  359.             glTexCoord2f (0, 1);
  360.             glVertex2f (x, y + h);
  361.  
  362.             glTexCoord2f (1, 1);
  363.             glVertex2f (x + w, y + h);
  364.  
  365.             glEnd ();
  366.  
  367.             glPopMatrix ();
  368.  
  369.             glClear (GL_DEPTH_BUFFER_BIT);
  370.             glBindTexture (GL_TEXTURE_2D, 0);
  371.         }
  372.         return;
  373.     }
  374.  
  375.     //
  376.     // draw background
  377.     //
  378.  
  379.     if (g_viewerSettings.showBackground && d_textureNames[0] && !g_viewerSettings.showTexture)
  380.     {
  381.         glMatrixMode (GL_PROJECTION);
  382.         glLoadIdentity ();
  383.  
  384.         glOrtho (0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f);
  385.  
  386.         glMatrixMode (GL_MODELVIEW);
  387.         glPushMatrix ();
  388.         glLoadIdentity ();
  389.  
  390.         glDisable (GL_CULL_FACE);
  391.         glEnable (GL_TEXTURE_2D);
  392.  
  393.         glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
  394.         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  395.  
  396.         glBindTexture (GL_TEXTURE_2D, d_textureNames[0]);
  397.  
  398.         glBegin (GL_TRIANGLE_STRIP);
  399.  
  400.         glTexCoord2f (0, 0);
  401.         glVertex2f (0, 0);
  402.  
  403.         glTexCoord2f (1, 0);
  404.         glVertex2f (1, 0);
  405.  
  406.         glTexCoord2f (0, 1);
  407.         glVertex2f (0, 1);
  408.  
  409.         glTexCoord2f (1, 1);
  410.         glVertex2f (1, 1);
  411.  
  412.         glEnd ();
  413.  
  414.         glPopMatrix ();
  415.  
  416.         glClear (GL_DEPTH_BUFFER_BIT);
  417.         glBindTexture (GL_TEXTURE_2D, 0);
  418.     }
  419.  
  420.     glMatrixMode (GL_PROJECTION);
  421.     glLoadIdentity ();
  422.     gluPerspective (65.0f, (GLfloat) w () / (GLfloat) h (), 1.0f, 4096.0f);
  423.  
  424.     glMatrixMode (GL_MODELVIEW);
  425.     glPushMatrix ();
  426.     glLoadIdentity ();
  427.  
  428.     glTranslatef(-g_viewerSettings.trans[0], -g_viewerSettings.trans[1], -g_viewerSettings.trans[2]);
  429.     
  430.     glRotatef (g_viewerSettings.rot[0], 1.0f, 0.0f, 0.0f);
  431.     glRotatef (g_viewerSettings.rot[1], 0.0f, 0.0f, 1.0f);
  432.  
  433.     // setup stencil buffer
  434.     if (g_viewerSettings.useStencil)
  435.     {
  436.         /* Don't update color or depth. */
  437.         glDisable(GL_DEPTH_TEST);
  438.         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  439.  
  440.         /* Draw 1 into the stencil buffer. */
  441.         glEnable(GL_STENCIL_TEST);
  442.         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  443.         glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
  444.  
  445.         /* Now render floor; floor pixels just get their stencil set to 1. */
  446.         drawFloor();
  447.  
  448.         /* Re-enable update of color and depth. */ 
  449.         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  450.         glEnable(GL_DEPTH_TEST);
  451.  
  452.         /* Now, only render where stencil is set to 1. */
  453.         glStencilFunc(GL_EQUAL, 1, 0xffffffff);  /* draw if ==1 */
  454.         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  455.     }
  456.  
  457.     g_vright[0] = g_vright[1] = g_viewerSettings.trans[2];
  458.  
  459.     if (g_viewerSettings.mirror)
  460.     {
  461.         glPushMatrix ();
  462.         glScalef (1, 1, -1);
  463.         glCullFace (GL_BACK);
  464.         setupRenderMode ();
  465.         g_studioModel.DrawModel ();
  466.         glPopMatrix ();
  467.     }
  468.  
  469.     if (g_viewerSettings.useStencil)
  470.         glDisable (GL_STENCIL_TEST);
  471.  
  472.     setupRenderMode ();
  473.  
  474.     glCullFace (GL_FRONT);
  475.     g_studioModel.DrawModel ();
  476.  
  477.     //
  478.     // draw ground
  479.     //
  480.  
  481.     if (g_viewerSettings.showGround)
  482.     {
  483.         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  484.         glEnable (GL_DEPTH_TEST);
  485.         glEnable (GL_CULL_FACE);
  486.  
  487.         if (g_viewerSettings.useStencil)
  488.             glFrontFace (GL_CW);
  489.         else
  490.             glDisable (GL_CULL_FACE);
  491.  
  492.         glEnable (GL_BLEND);
  493.         if (!d_textureNames[1])
  494.         {
  495.             glDisable (GL_TEXTURE_2D);
  496.             glColor4f (g_viewerSettings.gColor[0], g_viewerSettings.gColor[1], g_viewerSettings.gColor[2], 0.7f);
  497.             glBindTexture (GL_TEXTURE_2D, 0);
  498.         }
  499.         else
  500.         {
  501.             glEnable (GL_TEXTURE_2D);
  502.             glColor4f (1.0f, 1.0f, 1.0f, 0.6f);
  503.             glBindTexture (GL_TEXTURE_2D, d_textureNames[1]);
  504.         }
  505.  
  506.         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  507.         
  508.         drawFloor ();
  509.  
  510.         glDisable (GL_BLEND);
  511.  
  512.         if (g_viewerSettings.useStencil)
  513.         {
  514.             glCullFace (GL_BACK);
  515.             glColor4f (0.1f, 0.1f, 0.1f, 1.0f);
  516.             glBindTexture (GL_TEXTURE_2D, 0);
  517.             drawFloor ();
  518.  
  519.             glFrontFace (GL_CCW);
  520.         }
  521.         else
  522.             glEnable (GL_CULL_FACE);
  523.     }
  524.  
  525.     glPopMatrix ();
  526. }
  527.  
  528.  
  529.  
  530. int
  531. GlWindow::loadTexture (const char *filename, int name)
  532. {
  533.     if (!filename || !strlen (filename))
  534.     {
  535.         if (d_textureNames[name])
  536.         {
  537.             glDeleteTextures (1, (const GLuint *) &d_textureNames[name]);
  538.             d_textureNames[name] = 0;
  539.  
  540.             if (name == 0)
  541.                 strcpy (g_viewerSettings.backgroundTexFile, "");
  542.             else
  543.                 strcpy (g_viewerSettings.groundTexFile, "");
  544.         }
  545.  
  546.         return 0;
  547.     }
  548.  
  549.     mxImage *image = 0;
  550.  
  551.     char ext[16];
  552.     strcpy (ext, mx_getextension (filename));
  553.  
  554.     if (!mx_strcasecmp (ext, ".tga"))
  555.         image = mxTgaRead (filename);
  556.     else if (!mx_strcasecmp (ext, ".pcx"))
  557.         image = mxPcxRead (filename);
  558.     else if (!mx_strcasecmp (ext, ".bmp"))
  559.         image = mxBmpRead (filename);
  560.  
  561.     if (image)
  562.     {
  563.         if (name == 0)
  564.             strcpy (g_viewerSettings.backgroundTexFile, filename);
  565.         else
  566.             strcpy (g_viewerSettings.groundTexFile, filename);
  567.  
  568.         d_textureNames[name] = name + 1;
  569.  
  570.         if (image->bpp == 8)
  571.         {
  572.             mstudiotexture_t texture;
  573.             texture.width = image->width;
  574.             texture.height = image->height;
  575.  
  576.             g_studioModel.UploadTexture (&texture, (byte *) image->data, (byte *) image->palette, name + 1);
  577.         }
  578.         else
  579.         {
  580.             glBindTexture (GL_TEXTURE_2D, d_textureNames[name]);
  581.             glTexImage2D (GL_TEXTURE_2D, 0, 3, image->width, image->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);
  582.             glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  583.             glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  584.             glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  585.         }
  586.  
  587.         delete image;
  588.  
  589.         return name + 1;
  590.     }
  591.  
  592.     return 0;
  593. }
  594.  
  595.  
  596.  
  597. void
  598. GlWindow::dumpViewport (const char *filename)
  599. {
  600. #ifdef WIN32
  601.     redraw ();
  602.     int w = w2 ();
  603.     int h = h2 ();
  604.  
  605.     mxImage *image = new mxImage ();
  606.     if (image->create (w, h, 24))
  607.     {
  608. #if 0
  609.         glReadBuffer (GL_FRONT);
  610.         glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image->data);
  611. #else
  612.         HDC hdc = GetDC ((HWND) getHandle ());
  613.         byte *data = (byte *) image->data;
  614.         int i = 0;
  615.         for (int y = 0; y < h; y++)
  616.         {
  617.             for (int x = 0; x < w; x++)
  618.             {
  619.                 COLORREF cref = GetPixel (hdc, x, y);
  620.                 data[i++] = (byte) ((cref >> 0)& 0xff);
  621.                 data[i++] = (byte) ((cref >> 8) & 0xff);
  622.                 data[i++] = (byte) ((cref >> 16) & 0xff);
  623.             }
  624.         }
  625.         ReleaseDC ((HWND) getHandle (), hdc);
  626. #endif
  627.         if (!mxTgaWrite (filename, image))
  628.             mxMessageBox (this, "Error writing screenshot.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  629.  
  630.         delete image;
  631.     }
  632. #endif    
  633. }
  634.